package com.gitee.wsl.compose.chart.sample

import androidx.compose.foundation.layout.absolutePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.dp
import com.gitee.wsl.common.ui.draw.style.LineStyle
import com.gitee.wsl.compose.chart.Chart
import com.gitee.wsl.compose.chart.ChartLayout
import com.gitee.wsl.compose.chart.ExperimentalKoalaPlotApi
import com.gitee.wsl.compose.chart.SelectChangedListener
import com.gitee.wsl.compose.chart.SelectCheck
import com.gitee.wsl.compose.chart.generateHueColorPalette
import com.gitee.wsl.compose.chart.legend.Flow
import com.gitee.wsl.compose.chart.legend.Legend
import com.gitee.wsl.compose.chart.legend.LegendLocation
import com.gitee.wsl.compose.chart.xy.XYGraph
import com.gitee.wsl.compose.chart.xy.XYGraphScope
import com.gitee.wsl.compose.chart.xy.axis.model.CategoryAxisModel
import com.gitee.wsl.compose.chart.xy.axis.model.FloatLinearAxisModel
import com.gitee.wsl.compose.chart.xy.line.stairstep.StairstepPlot
import com.gitee.wsl.compose.chart.xy.model.PointEntry
import com.gitee.wsl.compose.modifier.layout.VerticalRotation
import com.gitee.wsl.compose.modifier.layout.rotateVertically
import com.gitee.wsl.compose.ui.widget.Symbol
import com.gitee.wsl.compose.modifier.layout
import kotlin.math.ceil

val stairStepSampleView = object : SampleView {
    override val name: String = "Stair Step"

    override val thumbnail = @Composable {
        ThumbnailTheme {
            StairStepSamplePlot(true, name)
        }
    }

    override val content: @Composable () -> Unit = @Composable {
        StairStepSamplePlot(false, "Rainfall")
    }
}

private val colorMap = buildMap {
    val colors = generateHueColorPalette(RainData.rainfall.size)
    var i = 0
    RainData.rainfall.forEach {
        put(it.key, colors[i++])
    }
}

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
@Suppress("MagicNumber")
private fun StairStepSamplePlot(thumbnail: Boolean, title: String) {
    ChartLayout(
        modifier = paddingMod,
        title = { ChartTitle(title) },
        legend = {selected,listener-> LegendView(thumbnail,selected,listener) },
        legendLocation = LegendLocation.BOTTOM
    ) {
        XYGraph(
            xAxisModel = CategoryAxisModel(RainData.months),
            yAxisModel = FloatLinearAxisModel(
                0f..(ceil(RainData.max / 50.0) * 50.0).toFloat(),
                minimumMajorTickSpacing = 50.dp,
            ),
            xAxisLabels = {
                if (!thumbnail) {
                    AxisLabel(it, Modifier.padding(top = 2.dp))
                }
            },
            xAxisTitle = { if (!thumbnail) AxisTitle("Month") },
            yAxisLabels = {
                if (!thumbnail) AxisLabel(it.toString(), Modifier.absolutePadding(right = 2.dp))
            },
            yAxisTitle = {
                if (!thumbnail) {
                    AxisTitle(
                        "Rainfall (mm)",
                        modifier = Modifier
                            .layout {
                                rotateVertically(VerticalRotation.COUNTER_CLOCKWISE)
                            }
                            .padding(bottom = padding)
                    )
                }
            }
        ) {
            RainData.rainfall.entries.sortedBy { it.key }.forEach { (city, rain) ->
                chart(
                    city,
                    rain.mapIndexed { index, d ->
                        PointEntry(RainData.months[index], d.toFloat())
                    }
                )
            }
        }
    }
}

@Composable
private fun XYGraphScope<String, Float>.chart(
    city: String,
    data: List<PointEntry<String, Float>>,
) {
    StairstepPlot(
        data = data,
        lineStyle = LineStyle(
            brush = SolidColor(colorMap[city] ?: Color.Black),
            strokeWidth = 2.dp
        )
    )
}

@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
private fun LegendView(thumbnail: Boolean = false,selectCheck: SelectCheck,selectChangedListener: SelectChangedListener?) {
    val cities = RainData.rainfall.keys.sorted()

    if (!thumbnail) {
        Surface(shadowElevation = 2.dp) {
            Legend.Flow(
                itemCount = cities.size,
                symbol = { i,selected ->
                    Symbol(
                        modifier = Modifier.size(padding),
                        fillBrush = SolidColor(colorMap[cities[i]] ?: Color.Black)
                    )
                },
                label = { i,selected,listener ->
                    Text(cities[i])
                },
                modifier = paddingMod,
                selectCheck = selectCheck,
                selectChangedListener = selectChangedListener
            )
        }
    }
}
